package com.middlegroup.subjectpay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.middlegroup.common.enums.ConfigKeyEnums;
import com.middlegroup.common.exception.ErrorMsg;
import com.middlegroup.common.model.NotifyRequest;
import com.middlegroup.common.model.SubjectpayQueryRequest;
import com.middlegroup.common.model.TransResult;
import com.middlegroup.common.utils.DateUtils;
import com.middlegroup.subjectpay.dto.TransRequest;
import com.middlegroup.subjectpay.entity.*;
import com.middlegroup.subjectpay.service.*;
import com.middlegroup.subjectpay.service.changpay.BaseConstant;
import com.middlegroup.subjectpay.service.changpay.ChanPayUtil;
import com.middlegroup.subjectpay.service.changpay.ChangpayCallbackRequest;
import com.middlegroup.subjectpay.service.helipay.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author pc
 * @date 2019/1/14
 */
@Service
@Slf4j
public class HelipayServiceImpl implements HelipayService {
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private HelipayDfBankCodeService helipayDfBankCodeService;
    @Resource
    private SubjectChannelConfigService subjectChannelConfigService;
    @Resource
    private SubjectOutThirdBillsService subjectOutThirdBillsService;

    @Resource
    private SubjectInThirdBillsService subjectInThirdBillsService;

    @Resource
    private ThirdProtocolBindCardService thirdProtocolBindCardService;

    @Resource
    private ThirdProtocolBindRecordService thirdProtocolBindRecordService;

    @Resource
    private SubjectInBillsService subjectInBillsService;

    @Resource
    private SubjectPayNotifyUtil subjectPayNotifyUtil;

    @Resource
    private SubjectInNotifyLogService subjectInNotifyLogService;

    @Override
    public TransResult df(TransRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        HelipayDfBankCode helipayDfBankCode = helipayDfBankCodeService.getBankCode(request.getCardBin());
        if (null == helipayDfBankCode || StringUtils.isBlank(helipayDfBankCode.getBankCode())) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.NONSUPPORT_BANK);
            return transResult;
        }

        String category = request.getChannelCode().getCode();

        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String privateKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PRIVATEKEY.getName());
        String publicKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PUBLICKEY.getName());
        String callBackUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.CALLBACKURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

//        String merchantNo="C1800248179";
//        String requestUrl="http://transfer.trx.helipay.com/trx/transfer/interface.action";
//        String privateKey="MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKpV2m7t35EmnqR0L1nUTY9yi6WKhq3G0Aq+mRcyWSgV++q247qUyrceEaW9aByzoB33Z9GTxHkj7Gr8s1txfWh/SIVAVKA6ivUPZoApGaWjJI95Q4WSOTwA79uIaaP3FN0l4FUC30LuTbtLCqmma2ikHElupJSE2giMHet3gWJBAgMBAAECgYAY9iPghbNxjftJlk0qGNaU4vBb/gTminAKYwwEPjiaiz4zk0GkIhHi6+EiLLOJITmhqpPoPoNYTU9kDkwqZmM+I863LHWxyWwfE75rVzo8gHo5VAbO7mXHN2dYJGc5aWPTlqDsSljQ2ttTEXa1qa20NWbXjajo0AwL6FnLTbHqwQJBANbJo2fs4ZvkeUVaMAche5eXY5S59x1hkiSTpNkazJpZwVfGtMCfFXSguciaZFFtszn4eB1SHT9u0iB57j166XUCQQDLBLhkKfNQjU6xDwDDCJdeASDZw8zMXEIxRRa0cVanHsY6hXMtUsBNh4e51bEd4lzxJiNL+osT0Qm8M55YszAdAkEAqObHaOIOR9jSxIa3XeQmnH6gAER83s3rbnfsGg3I91e9gpjvasmuxZfegLFoUeBCIEQTsHryJP+wnXlEr3QIQQJBAIhZKDnlTsuny9TwfZN/PqHc4iI+9Vm/EJmkjAYuJINjEMEXBW7IJ+0p/AbcNPMcJ02yTnxlzWhGuWITzOJHniUCQQDTsHMXxu+BHKORBFqnTLsiTh37VhUjsVhdLjh04CjYeukHHQCERT6LK9srfzTg8yFCuVvXMQ0FLA/gim2q1fOf";
//        String publicKey="该渠道不用这个字段值";
//        String callBackUrl="该渠道不用这个字段值";
//        String MD5Key="wyfnPHkJTsMhoBoNKHxGRL8vwl2oBPRm";

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(privateKey) || StringUtils.isBlank(publicKey) || StringUtils.isBlank(callBackUrl) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        Map<String, String> map = null;
        try {
            map = getDfParamMap(request, merchantNo, privateKey, helipayDfBankCode.getBankCode());
        } catch (Exception e) {
            log.error("合利宝代付组装请求数据失败,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }

        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<String, String>();
        for (String key : map.keySet()) {
            postParameters.add(key, map.get(key));
        }

        SubjectOutThirdBills subjectOutThirdBills = new SubjectOutThirdBills();
        subjectOutThirdBills.setSubjectCode(request.getSubjectCode());
        subjectOutThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectOutThirdBills.setBillNo(request.getBillNo());
        subjectOutThirdBills.setStatus(0);
        subjectOutThirdBills.setAmount(request.getAmount());
        subjectOutThirdBills.setRequestUrl(requestUrl);
        subjectOutThirdBills.setRequestText(JSON.toJSONString(postParameters));
        subjectOutThirdBills.setBeginTime(System.currentTimeMillis());
        subjectOutThirdBills.setServiceType(request.getServiceType());

        String str = null;
        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("调用合利宝支付代付接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }

        subjectOutThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectOutThirdBills.setEndTime(System.currentTimeMillis());

        if (StringUtils.isBlank(str)) {
            //默认交易处理中
            log.error("调用合利宝支付代付接口返回空,billNo:{}", request.getBillNo());
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            CreateOrderDfResponseVo orderResponseVo = null;
            String retStr = null;
            try {
                orderResponseVo = JSONObject.parseObject(str, CreateOrderDfResponseVo.class);
                String[] excludes = new String[]{"rt3_retMsg"};
                retStr = MyBeanUtils.convertToStr(orderResponseVo, excludes);
            } catch (Exception e) {
                log.error("代付解析合利宝返回数据出错,str:{},error:{}", str, e);
                transResult.setMsg(ErrorMsg.RETURN_DATA_ANALYZE_FAIL);
            }
            if (null != orderResponseVo && null != retStr) {
                String responseSign = orderResponseVo.getSign();
                retStr = retStr + HelipayConstants.SPLIT + MD5Key;
                String checkSign = Disguiser.disguiseMD5(retStr);

                //代付请状态能不设置为失败就不设置失败，设置成功会导致重复放款
                if (checkSign.equals(responseSign)) {
                    transResult.setTransNo(orderResponseVo.getRt6_serialNumber());
                    transResult.setMsg(orderResponseVo.getRt3_retMsg());

                    if ("0000".equals(orderResponseVo.getRt2_retCode())) {
                        //TODO 同步不返回成功
                    } else {//0 0001：订单已存在 0003：账户余额不足 0004:账户状态异常 0005:订单不存在 0006:打款超过限额
                        transResult.setTransStatus(2);
                        subjectOutThirdBills.setStatus(2);
                    }
                } else {
                    log.error("合利宝支付验签失败,billNo:{}", request.getBillNo());
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                }
            }
        }

        try {
            subjectOutThirdBillsService.insert(subjectOutThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }

    @Override
    public TransResult dfQuery(SubjectpayQueryRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        String category = request.getChannelCode();

        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String privateKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PRIVATEKEY.getName());
        String publicKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PUBLICKEY.getName());
        String callBackUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.CALLBACKURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(privateKey) || StringUtils.isBlank(publicKey) || StringUtils.isBlank(callBackUrl) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        QueryOrderDfVo queryOrderVo = new QueryOrderDfVo();
        queryOrderVo.setP1_bizType(BizTypeEnum.TransferQuery.name());
        queryOrderVo.setP2_orderId(request.getBillNo());
        queryOrderVo.setP3_customerNumber(merchantNo);
        Map<String, String> map = null;
        try {
            map = MyBeanUtils.convertBean(queryOrderVo);
            String orgStr = MyBeanUtils.convertToStr(map, null);
            String sign = RSA.sign(orgStr, RSA.getPrivateKey(privateKey));
            map.put("sign", sign);
        } catch (Exception e) {
            log.error("合利宝代付查询组装请求数据失败,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }

        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<String, String>();
        for (String key : map.keySet()) {
            postParameters.add(key, map.get(key));
        }

        SubjectOutThirdBills subjectOutThirdBills = new SubjectOutThirdBills();
        subjectOutThirdBills.setSubjectCode(request.getSubjectCode());
        subjectOutThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectOutThirdBills.setBillNo(request.getBillNo());
        subjectOutThirdBills.setStatus(0);
        subjectOutThirdBills.setAmount(request.getAmount());
        subjectOutThirdBills.setRequestUrl(requestUrl);
        subjectOutThirdBills.setRequestText(JSON.toJSONString(postParameters));
        subjectOutThirdBills.setBeginTime(System.currentTimeMillis());
        subjectOutThirdBills.setServiceType(request.getServiceType());

        String str = null;
        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("调用合利宝支付代付查询接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }

        subjectOutThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectOutThirdBills.setEndTime(System.currentTimeMillis());

        if (StringUtils.isBlank(str)) {
            //默认交易处理中
            log.error("调用合利宝支付代付查询接口返回空,billNo:{}", request.getBillNo());
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_RETURN_BLANK);
        } else {
            QueryOrderResponseDfVo queryOrderResponseVo = null;
            String checkSign = null;
            try {
                queryOrderResponseVo = JSONObject.parseObject(str, QueryOrderResponseDfVo.class);
                String[] excludes = new String[]{"rt3_retMsg", "rt8_reason"};
                String retStr = MyBeanUtils.convertToStr(queryOrderResponseVo, excludes) + HelipayConstants.SPLIT + MD5Key;
                checkSign = Disguiser.disguiseMD5(retStr);
            } catch (Exception e) {
                log.error("代付查询解析合利宝返回数据出错,str:{},error:{}", str, e);
            }

            if (null != queryOrderResponseVo && null != checkSign) {
                String responseSign = queryOrderResponseVo.getSign();
                if (checkSign.equals(responseSign)) {
                    transResult.setMsg(queryOrderResponseVo.getRt3_retMsg());
                    transResult.setTransNo(queryOrderResponseVo.getRt6_serialNumber());

                    if ("0000".equals(queryOrderResponseVo.getRt2_retCode())) {
                        //打款状态
                        String orderStatus = queryOrderResponseVo.getRt7_orderStatus();
                        switch (orderStatus) {
                            case "SUCCESS":
                                transResult.setTransStatus(1);
                                subjectOutThirdBills.setStatus(1);
                                break;
                            case "FAIL":
                                transResult.setTransStatus(2);
                                subjectOutThirdBills.setStatus(2);
                                break;
                            default://其他状态默认处理中
                                transResult.setTransStatus(0);
                                subjectOutThirdBills.setStatus(0);
                                break;
                        }
                    }
                } else {
                    log.error("合利宝代付查询验签失败,billNo:{}", request.getBillNo());
                    transResult.setMsg(ErrorMsg.RETURN_DATA_CHECK_SIGN_FAIL);
                }
            }
        }

        try {
            subjectOutThirdBillsService.insert(subjectOutThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }


    @Override
    public TransResult deduct(TransRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());
        String category = request.getChannelCode().getCode();

        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String desKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.DESKEY.getName());
        String callBackUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.CALLBACKURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(desKey) || StringUtils.isBlank(callBackUrl) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        Map map = null;
        try {
            map = getDsParamMap(request, merchantNo, desKey, callBackUrl, MD5Key);
        } catch (Exception e) {
            log.error("helipay 加密异常：{}", e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置请求参数
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<String, String>();
        postParameters.setAll(map);

        SubjectInThirdBills subjectInThirdBills = new SubjectInThirdBills();
        subjectInThirdBills.setSubjectCode(request.getSubjectCode());
        subjectInThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectInThirdBills.setBillNo(request.getBillNo());
        subjectInThirdBills.setStatus(0);
        subjectInThirdBills.setAmount(request.getAmount());
        subjectInThirdBills.setRequestUrl(requestUrl);
        subjectInThirdBills.setRequestText(JSON.toJSONString(map));
        subjectInThirdBills.setBeginTime(System.currentTimeMillis());
        subjectInThirdBills.setServiceType(request.getServiceType());
        String str = null;

        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("请求合利宝代扣接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        subjectInThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectInThirdBills.setEndTime(System.currentTimeMillis());

        CreateOrderDsResponseVo orderResponseVo = null;
        Map<String, String> assemblyRespOriSign = null;
        try {
            orderResponseVo = JSONObject.parseObject(str, CreateOrderDsResponseVo.class);
            assemblyRespOriSign = MyBeanUtils.convertBean(orderResponseVo, new LinkedHashMap());
        } catch (Exception e) {
            log.error("首次快捷支付解析合利宝返回数据出错:{}{}", str, e);
        }
        if (null != orderResponseVo && null != assemblyRespOriSign) {
            String responseSign = orderResponseVo.getSign();
            String oriMessage = MyBeanUtils.getSigned(assemblyRespOriSign, null, MD5Key);
            String checkSign = Disguiser.disguiseMD5(oriMessage.trim());
            if (checkSign.equals(responseSign)) {
                String msg = orderResponseVo.getRt3_retMsg();
                transResult.setMsg(msg);

                if ("0000".equals(orderResponseVo.getRt2_retCode())) {//受理成功
                    subjectInThirdBills.setStatus(0);
                    transResult.setTransStatus(0);
                    //TODO 2018.8.2目前改成不需要短信验证码的模式
                    request.setSmsCode("无短验模式");
                    transResult = this.firstKjconfirmPayment(request);

                } else {//受理失败或异常
                    transResult.setTransStatus(2);
                    subjectInThirdBills.setStatus(1);
                    transResult.setMsg(orderResponseVo.getRt3_retMsg());
                }
            } else {//未返回签名则认为失败
                transResult.setMsg("首次快捷支付请求结果验签失败");
                subjectInThirdBills.setStatus(2);
            }
        } else {
            subjectInThirdBills.setStatus(2);
            transResult.setMsg("首次快捷支付请求结果解析失败" + str);
        }
        try {
            subjectInThirdBillsService.insert(subjectInThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }
        return transResult;
    }


    /**
     * 合利宝首次支付
     *
     * @param request
     * @return
     */
    public TransResult firstKjconfirmPayment(TransRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());
        String category = request.getChannelCode().getCode();

        // 获取配置参数
        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

        // 校验配置
        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        Map map = null;
        try {
            map = getFirstKjQrPayParamMap(request, merchantNo, MD5Key);
        } catch (Exception e) {
            log.error("合利宝 首次快捷支付发送短信参数转换失败{}{}", request, e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置请求参数
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<String, String>();
        postParameters.setAll(map);
        SubjectInThirdBills subjectInThirdBills = new SubjectInThirdBills();
        subjectInThirdBills.setSubjectCode(request.getSubjectCode());
        subjectInThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectInThirdBills.setBillNo(request.getBillNo());
        subjectInThirdBills.setStatus(0);
        subjectInThirdBills.setAmount(request.getAmount());
        subjectInThirdBills.setRequestUrl(requestUrl);
        subjectInThirdBills.setRequestText(JSON.toJSONString(map));
        subjectInThirdBills.setBeginTime(System.currentTimeMillis());
        subjectInThirdBills.setServiceType(request.getServiceType());

        // 记录下绑卡记录
        ThirdProtocolBindRecord thirdProtocolBindRecord = new ThirdProtocolBindRecord();
        thirdProtocolBindRecord.setBillNo(request.getBillNo());
        thirdProtocolBindRecord.setMerchantBillNo(request.getMerchantBillNo());
        thirdProtocolBindRecord.setCardNo(request.getCardNo());
        thirdProtocolBindRecord.setIdCard(request.getIdCard());
        thirdProtocolBindRecord.setName(request.getName());
        thirdProtocolBindRecord.setPhone(request.getPhone());
        thirdProtocolBindRecord.setChannelCode(request.getChannelCode().getCode());
        thirdProtocolBindRecord.setSubjectCode(request.getSubjectCode());
        thirdProtocolBindRecord.setStatus(0);
        thirdProtocolBindRecordService.insert(thirdProtocolBindRecord);

        String str = null;
        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("调用合利宝首次快捷支付确认支付失败 {}{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        subjectInThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectInThirdBills.setEndTime(System.currentTimeMillis());

        if (StringUtils.isBlank(str)) {
            subjectInThirdBills.setResponseText("合利宝首次快捷支付确认支付返回空字符串交易号：" + request.getBillNo());
            subjectInThirdBills.setStatus(3);
            transResult.setMsg("首次快捷支付确认支付返回空字符串");
        } else {
            transResult.setTransStatus(0);
            ConfirmPayResponseVo orderResponseVo = null;
            Map<String, String> assemblyRespOriSign = null;
            try {
                orderResponseVo = JSONObject.parseObject(str, ConfirmPayResponseVo.class);
                assemblyRespOriSign = MyBeanUtils.convertBean(orderResponseVo, new LinkedHashMap());
            } catch (Exception e) {
                log.error("首次快捷支付确认支付解析合利宝返回数据出错:" + str, e);
            }
            if (null != orderResponseVo && null != assemblyRespOriSign) {
                String responseSign = orderResponseVo.getSign();
                String oriMessage = MyBeanUtils.getSigned(assemblyRespOriSign, null, MD5Key);
                String checkSign = Disguiser.disguiseMD5(oriMessage.trim());
                if (checkSign.equals(responseSign)) {
                    String msg = orderResponseVo.getRt3_retMsg();
                    transResult.setMsg(msg);
                    if ("0000".equals(orderResponseVo.getRt2_retCode())) {//受理成功
                        // 交易状态
                        String orderStatus = orderResponseVo.getRt9_orderStatus();
                        transResult.setTransNo(orderResponseVo.getRt6_serialNumber());
                        switch (orderStatus) {
                            case "SUCCESS":
                                subjectInThirdBills.setStatus(1);
                                transResult.setTransStatus(1);
                                // 首次交易时间
                                String tradeTime = orderResponseVo.getRt7_completeDate();
                                if (StringUtils.isNotBlank(tradeTime)) {
                                    transResult.setTransTime(DateUtils.convert(tradeTime, "yyyy-MM-dd HH:mm:ss").getTime());
                                } else {
                                    transResult.setTransTime(System.currentTimeMillis());
                                }

                                //TODO 确认支付成功会返回绑卡id，存起来
                                String bindId = orderResponseVo.getRt10_bindId();
                                // 绑定银行卡
                                saveBindCard(request.getPhone(), request.getName(), request.getIdCard(),
                                        request.getCardNo(), bindId, request.getSubjectCode(), request.getChannelCode().getCode());
                                break;
                            case "FAILED"://失败
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            case "CANCELLED"://已取消
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            case "REFUNDED"://已退款
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            default:
                                transResult.setTransStatus(0);
                                subjectInThirdBills.setStatus(0);
                                break;
                        }

                    } else if ("0001".equals(orderResponseVo.getRt2_retCode())) {
                        transResult.setTransStatus(0);
                        subjectInThirdBills.setStatus(0);
                    } else {//受理失败或异常
                        transResult.setTransStatus(2);
                        subjectInThirdBills.setStatus(2);
                        transResult.setMsg(orderResponseVo.getRt3_retMsg());
                        //TODO 为了验证码错误提示用户并重发验证码
                        if ("8015".equals(orderResponseVo.getRt2_retCode())) {
                            transResult.setValidCode(ErrorMsg.SMSCODE_FAIL);//验证码不正确的错误码
                        }
                    }
                } else {//未返回签名则认为失败
                    transResult.setMsg("首次快捷支付确认支付请求结果验签失败");
                    subjectInThirdBills.setStatus(2);
                }
            } else {
                subjectInThirdBills.setStatus(2);
                transResult.setMsg("首次快捷支付确认支付请求结果解析失败" + str);
            }
        }

        try {
            subjectInThirdBillsService.insert(subjectInThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }

    @Override
    public TransResult secondDeduct(TransRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());
        String category = request.getChannelCode().getCode();

        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String callBackUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.CALLBACKURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

        // 校验配置
        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(callBackUrl) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }
        Map map = null;
        try {
            map = getbindCardPayParamMap(request, merchantNo, callBackUrl, MD5Key);
        } catch (Exception e) {
            log.error("合利宝 首次快捷支付发送短信参数转换失败{}{}", request, e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        // 设置请求参数
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<String, String>();
        postParameters.setAll(map);
        SubjectInThirdBills subjectInThirdBills = new SubjectInThirdBills();
        subjectInThirdBills.setSubjectCode(request.getSubjectCode());
        subjectInThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectInThirdBills.setBillNo(request.getBillNo());
        subjectInThirdBills.setStatus(0);
        subjectInThirdBills.setAmount(request.getAmount());
        subjectInThirdBills.setRequestUrl(requestUrl);
        subjectInThirdBills.setRequestText(JSON.toJSONString(map));
        subjectInThirdBills.setBeginTime(System.currentTimeMillis());
        subjectInThirdBills.setServiceType(request.getServiceType());
        String str = null;
        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("调用合利宝首次快捷支付确认支付失败 {}{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }
        subjectInThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectInThirdBills.setEndTime(System.currentTimeMillis());
        // 结果处理
        if (StringUtils.isBlank(str)) {
            subjectInThirdBills.setResponseText("快捷支付确认支付返回空字符串交易号：" + request.getBillNo());
            subjectInThirdBills.setStatus(3);
            transResult.setMsg("快捷支付确认支付返回空字符串");
        } else {
            transResult.setTransStatus(0);
            BindCardPayResponseVo orderResponseVo = null;
            Map<String, String> assemblyRespOriSign = null;
            try {
                orderResponseVo = JSONObject.parseObject(str, BindCardPayResponseVo.class);
                assemblyRespOriSign = MyBeanUtils.convertBean(orderResponseVo, new LinkedHashMap());
            } catch (Exception e) {
                log.error("二次支付确认支付解析合利宝返回数据出错:" + str, e);
            }
            if (null != orderResponseVo && null != assemblyRespOriSign) {
                String responseSign = orderResponseVo.getSign();
                String oriMessage = MyBeanUtils.getSigned(assemblyRespOriSign, null, MD5Key);
                String checkSign = Disguiser.disguiseMD5(oriMessage.trim());
                if (checkSign.equals(responseSign)) {
                    String msg = orderResponseVo.getRt3_retMsg();
                    transResult.setMsg(msg);
                    if ("0000".equals(orderResponseVo.getRt2_retCode())) {//受理成功
                        // 交易状态
                        String orderStatus = orderResponseVo.getRt9_orderStatus();
                        transResult.setTransNo(orderResponseVo.getRt6_serialNumber());
                        switch (orderStatus) {
                            case "SUCCESS":
                                subjectInThirdBills.setStatus(1);
                                transResult.setTransStatus(1);
                                // 交易时间
                                String tradeTime = orderResponseVo.getRt7_completeDate();
                                if (StringUtils.isNotBlank(tradeTime)) {
                                    transResult.setTransTime(DateUtils.convert(tradeTime, "yyyy-MM-dd HH:mm:ss").getTime());
                                } else {
                                    transResult.setTransTime(System.currentTimeMillis());
                                }
                                break;
                            case "FAILED"://失败
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            case "CANCELLED"://已取消
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            case "REFUNDED"://已退款
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                transResult.setMsg(orderResponseVo.getRt3_retMsg());
                                break;
                            default:
                                transResult.setTransStatus(0);
                                subjectInThirdBills.setStatus(0);
                                break;
                        }

                    } else if ("0001".equals(orderResponseVo.getRt2_retCode())) {
                        transResult.setTransStatus(0);
                        subjectInThirdBills.setStatus(0);
                    } else {
                        transResult.setTransStatus(2);
                        subjectInThirdBills.setStatus(2);
                        transResult.setMsg(orderResponseVo.getRt3_retMsg());
                    }
                } else {//未返回签名则认为失败
                    transResult.setMsg("快捷支付确认支付请求结果验签失败");
                    subjectInThirdBills.setStatus(2);
                }
            } else {
                subjectInThirdBills.setStatus(2);
                transResult.setMsg("快捷支付确认支付请求结果解析失败" + str);
            }
        }

        try {
            subjectInThirdBillsService.insert(subjectInThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }

        return transResult;
    }

    @Override
    public TransResult deductQuery(SubjectpayQueryRequest request) {
        TransResult transResult = new TransResult();
        transResult.setBillNo(request.getBillNo());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setAmount(request.getAmount());
        transResult.setTransStatus(0);
        transResult.setTransTime(System.currentTimeMillis());

        String category = request.getChannelCode();

        String merchantNo = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MERCHANTNO.getName());
        String requestUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.REQUESTURL.getName());
        String privateKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PRIVATEKEY.getName());
        String publicKey = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.PUBLICKEY.getName());
        String callBackUrl = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.CALLBACKURL.getName());
        String MD5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());

        if (StringUtils.isBlank(requestUrl) || StringUtils.isBlank(merchantNo) || StringUtils.isBlank(privateKey) || StringUtils.isBlank(publicKey) || StringUtils.isBlank(callBackUrl) || StringUtils.isBlank(MD5Key)) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.INCOMPLETE_CONFIG_INFO);
            return transResult;
        }

        // 封装参数
        Map map = null;
        try {
            map = getOrderQueryParamMap(request.getBillNo(), merchantNo, MD5Key);
        } catch (Exception e) {
            log.error("合利宝 首次快捷支付发送短信参数转换失败{}{}", request, e);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.DATA_ENCRYPTION_FAIL);
            return transResult;
        }
        SubjectInThirdBills subjectInThirdBills = new SubjectInThirdBills();
        subjectInThirdBills.setSubjectCode(request.getSubjectCode());
        subjectInThirdBills.setMerchantBillNo(request.getMerchantBillNo());
        subjectInThirdBills.setBillNo(request.getBillNo());
        subjectInThirdBills.setStatus(0);
        subjectInThirdBills.setAmount(request.getAmount());
        subjectInThirdBills.setRequestUrl(requestUrl);
        subjectInThirdBills.setRequestText(JSON.toJSONString(map));
        subjectInThirdBills.setBeginTime(System.currentTimeMillis());
        subjectInThirdBills.setServiceType(request.getServiceType());

        // 请求参数
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
        postParameters.setAll(map);
        String str = null;
        try {
            str = restTemplate.postForObject(requestUrl, postParameters, String.class);
        } catch (Exception e) {
            log.error("请求合利宝订单查询接口异常,billNo:{},error:{}", request.getBillNo(), e);
            transResult.setMsg(ErrorMsg.PAY_INTERFACE_CALL_FAIL);
        }

        subjectInThirdBills.setResponseText((StringUtils.isNotBlank(str) && str.length() > 4000) ? str.substring(0, 4000) : str);
        subjectInThirdBills.setEndTime(System.currentTimeMillis());
        if (StringUtils.isBlank(str)) {
            subjectInThirdBills.setResponseText("合利宝首次快捷支付确认支付返回空字符串交易号：" + request.getBillNo());
            subjectInThirdBills.setStatus(3);
            transResult.setMsg("首次快捷支付确认支付返回空字符串");
        } else {
            transResult.setTransStatus(0);
            QueryOrderResponseVo queryOrderResponseVo = null;
            Map<String, String> assemblyRespOriSign = null;
            try {
                queryOrderResponseVo = JSONObject.parseObject(str, QueryOrderResponseVo.class);
                assemblyRespOriSign = MyBeanUtils.convertBean(queryOrderResponseVo, new LinkedHashMap());
            } catch (Exception e) {
                log.error("快捷支付查询解析合利宝返回数据出错:{}{}", str, e);
            }
            // 判断返回结果
            if (null != queryOrderResponseVo && null != assemblyRespOriSign) {
                String responseSign = queryOrderResponseVo.getSign();
                String oriMessage = MyBeanUtils.getSigned(assemblyRespOriSign, null, MD5Key);
                String checkSign = Disguiser.disguiseMD5(oriMessage.trim());
                if (checkSign.equals(responseSign)) {
                    String msg = queryOrderResponseVo.getRt3_retMsg();
                    transResult.setMsg(msg);
                    if ("0000".equals(queryOrderResponseVo.getRt2_retCode()) || "8000".equals(queryOrderResponseVo.getRt2_retCode())) {//受理成功
                        // 交易状态
                        String orderStatus = queryOrderResponseVo.getRt9_orderStatus();
                        transResult.setTransNo(queryOrderResponseVo.getRt10_serialNumber());
                        switch (orderStatus) {
                            case "SUCCESS":
                                subjectInThirdBills.setStatus(1);
                                transResult.setTransStatus(1);

                                String tradeTime = queryOrderResponseVo.getRt8_completeDate();
                                if (StringUtils.isNotBlank(tradeTime)) {
                                    transResult.setTransTime(DateUtils.convert(tradeTime, "yyyy-MM-dd HH:mm:ss").getTime());
                                } else {
                                    transResult.setTransTime(System.currentTimeMillis());
                                }
                                // 绑定银卡id
                                String bindId = queryOrderResponseVo.getRt14_bindId();
                                //TODO 确认支付成功会返回绑卡id，存起来
                                ThirdProtocolBindRecord thirdProtocolBindRecord = new ThirdProtocolBindRecord();
                                thirdProtocolBindRecord.setMerchantBillNo(request.getMerchantBillNo());
                                ThirdProtocolBindRecord findRecord = thirdProtocolBindRecordService.getLastOne(thirdProtocolBindRecord);
                                if (findRecord != null) {
                                    // 绑定银行卡
                                    saveBindCard(findRecord.getPhone(), findRecord.getName(), findRecord.getIdCard(),
                                            findRecord.getCardNo(), bindId, findRecord.getSubjectCode(), findRecord.getChannelCode());
                                }
                                break;
                            case "FAILED"://失败
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                break;
                            case "CANCELLED"://已取消
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                break;
                            case "REFUNDED"://已退款
                                transResult.setTransStatus(2);
                                subjectInThirdBills.setStatus(2);
                                break;
                            default:
                                transResult.setTransStatus(0);
                                subjectInThirdBills.setStatus(0);
                                break;
                        }
                    } else {//受理失败或异常
                        transResult.setTransStatus(2);
                        subjectInThirdBills.setStatus(2);
                    }
                } else {//未返回签名则认为失败
                    transResult.setMsg("快捷支付查询请求结果验签失败");
                    subjectInThirdBills.setStatus(2);
                }
            } else {
                subjectInThirdBills.setStatus(2);
                transResult.setMsg("快捷支付查询请求结果解析失败" + str);
            }
        }

        try {
            subjectInThirdBillsService.insert(subjectInThirdBills);
        } catch (Exception e) {
            log.error("合利宝代付插入第三方订单表异常,billNo:{},error:{}", request.getBillNo(), e);
        }
        return transResult;
    }

    @Override
    public String deductNotify(BindCardPayResponseVo request) {
        String result = "";

        //记录回调原始数据
        SubjectInNotifyLog subjectInNotifyLog = new SubjectInNotifyLog();
        subjectInNotifyLog.setBillNo(request.getRt5_orderId());
        subjectInNotifyLog.setCallbackText(JSONObject.toJSONString(request));
        //默认回调处理状态为处理中
        subjectInNotifyLog.setStatus(0);
        //默认订单交易状态为处理中
        subjectInNotifyLog.setTransStatus(0);
        subjectInNotifyLog.setCallbackText(JSONObject.toJSONString(request));
        subjectInNotifyLog.setMsg("回调处理中");
        boolean rt = subjectInNotifyLogService.insert(subjectInNotifyLog);
        if (!rt) {
            log.error("插入回调日志表失败,request:{}", request);
            return result;
        }

        //查询回调对应的订单信息
        SubjectInBills subjectInBillsFind = new SubjectInBills();
        subjectInBillsFind.setBillNo(request.getRt5_orderId());
        SubjectInBills subjectInBills = subjectInBillsService.getLastOneInBills(subjectInBillsFind);
        if (null == subjectInBills) {
            log.error("未查询到该笔订单,request:{}", request);
            return result;
        }
        subjectInNotifyLog.setSubjectCode(subjectInBills.getSubjectCode());
        subjectInNotifyLog.setMerchantBillNo(subjectInBills.getMerchantBillNo());

        //转发到支付中台的回调对象
        NotifyRequest notifyRequest = new NotifyRequest();
        notifyRequest.setMerchantBillNo(subjectInBills.getMerchantBillNo());
        notifyRequest.setBillNo(subjectInBills.getBillNo());
        notifyRequest.setTransStatus(0);
        notifyRequest.setMsg("回调处理中");
        notifyRequest.setTransTime(System.currentTimeMillis());
        notifyRequest.setAmount(subjectInBills.getAmount());

        String category = subjectInBills.getChannelCode();
        String md5Key = subjectChannelConfigService.getConfigString(category, ConfigKeyEnums.MD5KEY.getName());
        Map<String, String> assemblyRespOriSign = null;
        try {
            assemblyRespOriSign = MyBeanUtils.convertBean(request, new LinkedHashMap());
        } catch (Exception e) {
            log.error("首次快捷支付确认支付解析合利宝返回数据出错:", e);
        }
        if (null != request && null != assemblyRespOriSign) {
            String responseSign = request.getSign();
            String oriMessage = MyBeanUtils.getSigned(assemblyRespOriSign, null, md5Key);
            String checkSign = Disguiser.disguiseMD5(oriMessage.trim());
            // 签名处理
            if (checkSign.equals(responseSign)) {
                // 待处理状态 更新
                if ((subjectInBills.getStatus().intValue() == 0 || subjectInBills.getStatus().intValue() == 3)) {
                    if ("0000".equals(request.getRt2_retCode())) {//受理成功
                        String orderStatus = request.getRt9_orderStatus();
                        String transNo = request.getRt6_serialNumber();
                        String msg = request.getRt3_retMsg();
                        subjectInNotifyLog.setStatus(1);
                        subjectInNotifyLog.setTransNo(transNo);
                        subjectInNotifyLog.setMsg(msg);
                        notifyRequest.setTransNo(transNo);
                        notifyRequest.setMsg(msg);

                        switch (orderStatus) {
                            case "SUCCESS":
                                subjectInNotifyLog.setStatus(1);
                                notifyRequest.setTransStatus(1);

                                String tradeTime = request.getRt7_completeDate();
                                if (StringUtils.isNotBlank(tradeTime)) {
                                    notifyRequest.setTransTime(DateUtils.convert(tradeTime, "yyyy-MM-dd HH:mm:ss").getTime());
                                } else {
                                    notifyRequest.setTransTime(System.currentTimeMillis());
                                }
                                // 绑定银卡id
                                String bindId = request.getRt10_bindId();
                                //TODO 确认支付成功会返回绑卡id，存起来
                                ThirdProtocolBindRecord thirdProtocolBindRecord = new ThirdProtocolBindRecord();
                                thirdProtocolBindRecord.setMerchantBillNo(subjectInBills.getMerchantBillNo());
                                ThirdProtocolBindRecord findRecord = thirdProtocolBindRecordService.getLastOne(thirdProtocolBindRecord);
                                if (findRecord != null) {
                                    // 绑定银行卡
                                    saveBindCard(findRecord.getPhone(), findRecord.getName(), findRecord.getIdCard(),
                                            findRecord.getCardNo(), bindId, findRecord.getSubjectCode(), findRecord.getChannelCode());
                                }
                                break;
                            case "FAILED"://失败
                                notifyRequest.setTransStatus(2);
                                subjectInNotifyLog.setStatus(2);
                                break;
                            case "CANCELLED"://已取消
                                notifyRequest.setTransStatus(2);
                                subjectInNotifyLog.setStatus(2);
                                break;
                            case "REFUNDED"://已退款
                                notifyRequest.setTransStatus(2);
                                subjectInNotifyLog.setStatus(2);
                                break;
                            default:
                                notifyRequest.setTransStatus(0);
                                subjectInNotifyLog.setStatus(0);
                                break;
                        }
                    } else if ("0001".equals(request.getRt2_retCode())) {
                        notifyRequest.setTransStatus(0);
                        subjectInNotifyLog.setStatus(0);
                    } else {//受理失败或异常
                        notifyRequest.setTransStatus(2);
                        subjectInNotifyLog.setStatus(2);
                    }
                    // 结果状态
                    int transStatus = notifyRequest.getTransStatus().intValue();
                    if (transStatus == 1 || transStatus == 2) {
                        //更新订单表状态
                        subjectInBills.setStatus(transStatus);
                        subjectInBillsService.updateById(subjectInBills);
                        try {
                            //TODO 通知回调支付中台
                            subjectPayNotifyUtil.notifyPay(subjectInBills.getSubjectCode(), "notify/deduct", notifyRequest);
                        } catch (Exception e) {
                            log.error("合利宝回调支付中台异常，notifyRequest：{},error：{}", notifyRequest, e);
                        }
                    }
                } else {
                    subjectInNotifyLog.setMsg("订单状态已确定,不处理");
                }
                result = "SUCCESS";
            } else {
                //验签不通过
                //直接返回不处理业务
                subjectInNotifyLog.setStatus(2);
                subjectInNotifyLog.setMsg("支付回调验签不通过");
                log.error("合利宝支付回调验签失败,request:{}", request);
            }
        }
        //记录通知第三方支付公司的信息
        subjectInNotifyLog.setResponseText(result);
        try {
            subjectInNotifyLogService.updateById(subjectInNotifyLog);
        } catch (Exception e) {
            log.error("更新支付回调记录表失败,request:{},error:{}", request, e);
        }
        return result;
    }

    /**
     * 保存绑卡记录
     *
     * @param phone
     * @param name
     * @param idCard
     * @param cardNo
     * @param bindId
     * @param subjectCode
     * @param channleCode
     */
    private void saveBindCard(String phone, String name, String idCard, String cardNo, String bindId, String subjectCode, String channleCode) {
        ThirdProtocolBindCard thirdProtocolBindCardFind = new ThirdProtocolBindCard();
        thirdProtocolBindCardFind.setSubjectCode(subjectCode);
        thirdProtocolBindCardFind.setChannelCode(channleCode);
        thirdProtocolBindCardFind.setCardNo(cardNo);
        thirdProtocolBindCardFind.setIdCard(idCard);
        ThirdProtocolBindCard thirdProtocolBindCard = thirdProtocolBindCardService.getLastOne(thirdProtocolBindCardFind);
        if (null == thirdProtocolBindCard) {
            thirdProtocolBindCardFind.setName(name);
            thirdProtocolBindCardFind.setPhone(phone);
            thirdProtocolBindCardFind.setProtocolNo(bindId);
            thirdProtocolBindCardFind.setStatus(1);
            thirdProtocolBindCardService.insert(thirdProtocolBindCardFind);
        } else {
            thirdProtocolBindCard.setPhone(phone);
            thirdProtocolBindCard.setProtocolNo(bindId);
            thirdProtocolBindCard.setStatus(1);
            thirdProtocolBindCardService.updateById(thirdProtocolBindCard);
        }
    }

    /**
     * 组装请求业务参数
     *
     * @param request        业务参数
     * @param customerNumber 商户号
     * @param privateKey     私钥
     * @param bankCode       银行编码
     * @return
     * @throws Exception
     */
    private Map<String, String> getDfParamMap(TransRequest request, String customerNumber, String privateKey, String bankCode) throws Exception {
        CreateOrderDfVo createOrderDfVo = new CreateOrderDfVo();
        createOrderDfVo.setP1_bizType(BizTypeEnum.Transfer.name());
        createOrderDfVo.setP2_orderId(request.getBillNo());
        createOrderDfVo.setP3_customerNumber(customerNumber);
        createOrderDfVo.setP4_amount(request.getAmount().setScale(2, BigDecimal.ROUND_HALF_DOWN).toString());
        createOrderDfVo.setP5_bankCode(bankCode);
        createOrderDfVo.setP6_bankAccountNo(request.getCardNo());
        createOrderDfVo.setP7_bankAccountName(request.getName());
        createOrderDfVo.setP8_biz(BizEnum.B2C.name());
        createOrderDfVo.setP10_feeType(FeeTypeEnum.PAYER.name());
        createOrderDfVo.setP11_urgency("true");
        Map<String, String> map = MyBeanUtils.convertBean(createOrderDfVo);

        String orgStr = MyBeanUtils.convertToStr(map, null);
        String sign = RSA.sign(orgStr, RSA.getPrivateKey(privateKey));
        map.put("sign", sign);

        return map;
    }


    /**
     * 代扣请求参数
     *
     * @param request
     * @param customerNumber
     * @param desKey
     * @param callbackUrl
     * @param md5Key
     * @return
     * @throws Exception
     */
    private Map getDsParamMap(TransRequest request, String customerNumber, String desKey, String callbackUrl, String md5Key) throws Exception {
        CreateOrderDsVo createOrderVo = new CreateOrderDsVo();
        createOrderVo.setP1_bizType(BizTypeEnum.QuickPayCreateOrder.name());
        createOrderVo.setP2_customerNumber(customerNumber);
        createOrderVo.setP3_userId(request.getIdCard());
        createOrderVo.setP4_orderId(request.getBillNo());
        createOrderVo.setP5_timestamp(DateUtils.convert(new Date(), DateUtils.DATE_TIMESTAMP_SHORT_FORMAT));
        createOrderVo.setP6_payerName(request.getName());
        createOrderVo.setP7_idCardType(HelipayConstants.IDCARDTYPE);
        createOrderVo.setP8_idCardNo(Des3Encryption.encode(desKey, request.getIdCard()));
        createOrderVo.setP9_cardNo(Des3Encryption.encode(desKey, request.getCardNo()));
        createOrderVo.setP13_phone(Des3Encryption.encode(desKey, request.getPhone()));
        createOrderVo.setP14_currency(HelipayConstants.CNY);
        createOrderVo.setP15_orderAmount(request.getAmount().setScale(2, BigDecimal.ROUND_HALF_DOWN).toString());
        createOrderVo.setP16_goodsName("金融投资");
        createOrderVo.setP18_terminalType("OTHER");
        createOrderVo.setP19_terminalId(request.getBillNo());
        createOrderVo.setP20_orderIp("127.0.0.1");
        createOrderVo.setP21_period("30");//订单有效时间
        createOrderVo.setP22_periodUnit("Minute");//有效时间单位
        createOrderVo.setP23_serverCallbackUrl(callbackUrl);
        createOrderVo.setP24_isEncrypt("TRUE");//是否加密

        Map<String, String> map = MyBeanUtils.convertBean(createOrderVo, new LinkedHashMap());
        String[] excludes = {"P24_isEncrypt"};//不参与签名的
        String oriMessage = MyBeanUtils.getSigned(map, excludes, md5Key);
        log.debug("签名原文串：{}", oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.debug("签名串：{}", sign);
        map.put("sign", sign);
        log.debug("发送参数：{}", map);
        return map;
    }

    /**
     * 绑卡记录
     *
     * @param request
     * @param customerNumber
     * @param callbackUrl
     * @param md5Key
     * @return
     * @throws Exception
     */
    private Map getbindCardPayParamMap(TransRequest request, String customerNumber, String callbackUrl, String md5Key) throws Exception {
        BindCardPayVo bindCardPayVo = new BindCardPayVo();
        bindCardPayVo.setP1_bizType(BizTypeEnum.QuickPayBindPay.name());
        bindCardPayVo.setP2_customerNumber(customerNumber);
        bindCardPayVo.setP3_bindId(request.getBindId());
        bindCardPayVo.setP4_userId(request.getIdCard());
        bindCardPayVo.setP5_orderId(request.getBillNo());
        bindCardPayVo.setP6_timestamp(DateUtils.convert(new Date(), DateUtils.DATE_TIMESTAMP_SHORT_FORMAT));
        bindCardPayVo.setP7_currency(HelipayConstants.CNY);
        bindCardPayVo.setP8_orderAmount(request.getAmount().setScale(2, BigDecimal.ROUND_HALF_DOWN).toString());
        bindCardPayVo.setP9_goodsName("金融投资");
        bindCardPayVo.setP11_terminalType("OTHER");
        bindCardPayVo.setP12_terminalId(request.getBillNo());
        bindCardPayVo.setP13_orderIp("127.0.0.1");
        bindCardPayVo.setP14_period("30");//订单有效时间
        bindCardPayVo.setP15_periodUnit("Minute");//有效时间单位
        bindCardPayVo.setP16_serverCallbackUrl(callbackUrl);

        Map<String, String> map = MyBeanUtils.convertBean(bindCardPayVo, new LinkedHashMap());
        String[] excludes = {"P17_validateCode"};//不参与签名的
        String oriMessage = MyBeanUtils.getSigned(map, excludes, md5Key);
        log.debug("签名原文串：{}", oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.debug("签名串：{}", sign);
        map.put("sign", sign);
        log.debug("发送参数：{}", map);
        return map;
    }


    /**
     * 首次支付签名
     *
     * @param request
     * @param customerNumber
     * @param md5Key
     * @return
     * @throws Exception
     */
    private Map getFirstKjQrPayParamMap(TransRequest request, String customerNumber, String md5Key) throws Exception {
        ConfirmPayVo confirmPayVo = new ConfirmPayVo();
        confirmPayVo.setP1_bizType(BizTypeEnum.QuickPayConfirmPay.name());
        confirmPayVo.setP2_customerNumber(customerNumber);
        confirmPayVo.setP3_orderId(request.getBillNo());
        confirmPayVo.setP4_timestamp(DateUtils.convert(new Date(), DateUtils.DATE_TIMESTAMP_SHORT_FORMAT));
        confirmPayVo.setP5_validateCode(request.getSmsCode());//支付短信验证码
        confirmPayVo.setP6_orderIp("127.0.0.1");

        Map<String, String> map = MyBeanUtils.convertBean(confirmPayVo, new LinkedHashMap());
        String oriMessage = MyBeanUtils.getSigned(map, null, md5Key);
        log.debug("签名原文串：{}", oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.debug("签名串：{}", sign);
        map.put("sign", sign);
        log.debug("发送参数：{}", map);
        return map;
    }

    /**
     * 订单查询
     *
     * @param billNo
     * @param customerNumber
     * @param md5Key
     * @return
     * @throws Exception
     */
    private Map getOrderQueryParamMap(String billNo, String customerNumber, String md5Key) throws Exception {
        QueryOrderVo queryOrderVo = new QueryOrderVo();
        queryOrderVo.setP1_bizType(BizTypeEnum.QuickPayQuery.name());
        queryOrderVo.setP2_orderId(billNo);
        queryOrderVo.setP3_customerNumber(customerNumber);

        Map<String, String> map = MyBeanUtils.convertBean(queryOrderVo, new LinkedHashMap());
        String oriMessage = MyBeanUtils.getSigned(map, null, md5Key);
        log.debug("签名原文串：{}", oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.debug("签名串：{}", sign);
        map.put("sign", sign);
        log.debug("发送参数：{}", map);
        return map;
    }

}

